package data;

import java.sql.*;
import java.util.*;

public class Database
{
    private Connection m_DBConn;
    private String m_URL;
    private String m_User;
    private String m_Password;
    
    private GridFactory m_GridFactory;
    private GridSampleFactory m_GridSampleFactory;
    private CellSampleFactory m_CellSampleFactory;
    
    public Database( String host, int port, String dbname, String dbuser, String dbpass )
    {
	m_URL = "jdbc:postgresql://" + host + ":" + port + "/" + dbname;
	m_User = dbuser;
	m_Password = dbpass;
	
	try {
	    Class.forName( "org.postgresql.Driver" );
	    m_DBConn = DriverManager.getConnection( m_URL, m_User, m_Password );
	} catch( SQLException sqle ) {
	    System.err.println( "SQL Error: " + sqle.getMessage() );
	    sqle.printStackTrace();
	    System.exit(1);
	} catch( ClassNotFoundException cnf ) {
	    System.err.println( "Could not find PSQL driver: " + cnf.getMessage() );
	    cnf.printStackTrace();
	    System.exit(1);
	}
	
	m_GridFactory = new GridFactory( this );
	m_GridSampleFactory = new GridSampleFactory( this );
	m_CellSampleFactory = new CellSampleFactory( this );
    }
    
    public void execUpdate( String sql )
    {
	//System.out.println( "update: " + sql );
	try {
	    Statement stmt = m_DBConn.createStatement();
	    stmt.executeUpdate( sql );
	    
	} catch( SQLException sqle ) {
	    System.err.println( "SQL Error: " + sqle.getMessage() );
	    sqle.printStackTrace();
	    System.exit(1);
	}
    }
    
    public int execInsert( String sql, String seq )
    {
	int key = -1;
	
	try {
	    Statement stmt = m_DBConn.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY );
	    
	    //System.out.println ( "insert: " + sql );
	    
	    stmt.executeUpdate( sql );
	    ResultSet rs = stmt.executeQuery( "select currval('" + seq + "')" );
	    while( rs.next() ) {
		key = rs.getInt( 1 ) - 1;
	    }
	    
	    //System.out.println( "KEY=" + key  );
	    
	} catch( SQLException sqle ) {
	    System.err.println( "SQL Error: " + sqle.getMessage() );
	    sqle.printStackTrace();
	    System.exit(1);
	}
	
	return key;
    }
    
    public ResultSet execQuery( String sql )
    {
	try {
	    Statement stmt = m_DBConn.createStatement();
	    return stmt.executeQuery( sql );
	    
	} catch( SQLException sqle ) {
	    System.err.println( "SQL Error: " + sqle.getMessage() );
	    sqle.printStackTrace();
	    System.exit(1);
	    
	    return null;
	}
    }
    
    public GridFactory getGridFactory()
    {
	return m_GridFactory;
    }
    public GridSampleFactory getGridSampleFactory()
    {
	return m_GridSampleFactory;
    }
    public CellSampleFactory getCellSampleFactory()
    {
	return m_CellSampleFactory;
    }
    
    // -------------- static methods --------------
    
    private static Database s_Singleton;
    
    public static void Initialize(  String host, int port, String dbname, String dbuser, String dbpass )
    {
	s_Singleton = new Database( host, port, dbname, dbuser, dbpass );
    }
    
    public static Database GetInstance()
    {
	return s_Singleton;
    }
    
    private static void printRS( LinkedList l, String title )
    {
	System.out.println( title );
	System.out.println( l.size() );
	
	ListIterator iter = l.listIterator(0);
	while( iter.hasNext() ) {
	    System.out.println( iter.next() );
	}
    }
    
    public static void main( String[] args ) throws Exception
    {
	//Initialize( "helsinki.cc.gatech.edu", 9876, "ds3", "ds3", "EarthSim" );
	//Initialize( "mikkeli.cc.gatech.edu", 9876, "ds3", "ds3", "EarthSim" );
	Initialize( "localhost", 9876, "ds3", "ds3", "EarthSim" );
	
	Grid g = GetInstance().getGridFactory().create(); //GetInstance().getGridFactory().lookup( 21 );
	g.param_precision_digits = 3;
	g.param_geographic_accuracy = 20;
	g.param_temporal_accuracy = 40;
	g.phys_axial_tilt = 5;
	g.phys_orbital_eccentricity = 1.1;
	g.sim_grid_spacing = 20;
	g.sim_time_step = 600;
	g.save();
	
	java.util.GregorianCalendar gc = new java.util.GregorianCalendar();
	java.util.Date t = new java.util.Date( gc.getTime().getTime() );

	GridSample gs = GetInstance().getGridSampleFactory().create();
	gs.grid_id = g.getID();
	gs.time = t;
	gs.sun_theta = 0.0;
	gs.sun_phi = 0.0;
	gs.save();
	
	CellSample cs = GetInstance().getCellSampleFactory().create();
	cs.coord_theta = 0.0;
	cs.coord_phi = 0.0;
	cs.coord_radius = 10.0;
	cs.coord_latitude = 0.0;
	cs.coord_longitude = 0.0;
	cs.grid_id = g.getID();
	cs.time = t;
	cs.value = 15.0;
	cs.save();
	
	
	printRS( GetInstance().getGridFactory().find("param_precision_digits=2"), "grid" );
	printRS( GetInstance().getGridSampleFactory().findAll(), "gridsample" );
	
	printRS( GetInstance().getCellSampleFactory().findAll(), "cellsample" );

	//double geoTolerance, int minutesTolerance, int precisionDigits, double axialTilt, double eccentricity, Database db
	Interpolator interp = new Interpolator( 1.5, 40000, 2, 5, 1.1, GetInstance() );
	System.out.println( "iVal=" + interp.interpolatedValue( 0.0, 0.0, gc ) );
    }
}
